#include <cuda.h>
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

#include "cuda_util.h"
#include "cush_free.h"

/**
 *
 * This function frees the elements in dbuff
 *
 **/
void cush_member_free(cush_dbuff_t* dbuff){
    free(dbuff->id);
    free(dbuff->size);
    free(dbuff->offset);
    free(dbuff->ptr);
    free(dbuff->stream);
}

/**
 *
 * This function frees the members in dbuff and dbuff itself
 *
 **/
void cush_free(cush_dbuff_t* dbuff){
    cush_member_free(dbuff);

    free(dbuff);
}

/**
 *
 * This function frees the elements in dbuff, AND the 
 * device memory associated with dbuff 
 *
 **/
void cush_deep_member_free(cush_dbuff_t* dbuff){
    int i = 0;
	#pragma omp parallel for num_threads(dbuff->ndevices)
	for(i = 0; i < dbuff->ndevices; i++){
        int th_id = omp_get_thread_num();
        //int th_id = dbuff->id[i];
        //printf("Thread %d freeing on device %d at %lu\n", th_id, dbuff->id[i], dbuff->ptr[dbuff->id[i]]);
		cudaSetDevice(dbuff->id[i]);
		cudaFree(dbuff->ptr[dbuff->id[i]]);
		//cuMemAlloc(&(dbuff->ptr[i]),  dbuff->size[i]);
		checkCUDAError("cush free() failed",th_id);
    }

    cush_member_free(dbuff);
}

/**
 *
 * This function frees the elements in dbuff, dbuff itself, AND the 
 * device memory associated with dbuff 
 *
 **/
void cush_deep_free(cush_dbuff_t* dbuff){
    int i = 0;
	#pragma omp parallel for num_threads(dbuff->ndevices)
	for(i = 0; i < dbuff->ndevices; i++){
        int th_id = omp_get_thread_num();
        //int th_id = dbuff->id[i];
        //printf("Thread %d freeing on device %d at %lu\n", th_id, dbuff->id[i], dbuff->ptr[dbuff->id[i]]);
		cudaSetDevice(dbuff->id[i]);

		cudaFree(dbuff->ptr[dbuff->id[i]]);
		checkCUDAError("cush free() failed",th_id);
    }

    cush_free(dbuff);
}

/* vim: set sw=4 sts=4 et foldmethod=syntax syntax=c : */
